package com.gitee.wsl.transform

import com.gitee.wsl.ext.base.Flag
import com.gitee.wsl.struct.prioritizer.DefaultPrioritizer
import com.gitee.wsl.struct.prioritizer.Prioritizer
import com.gitee.wsl.ext.collection.forEachIndexedExtended

/**
 * 转换结构,对输入对象 进行 循环条件转换.
 */
fun sampleTransformer(transformPrioritizer: Prioritizer<Transform<Any, Any>> = DefaultPrioritizer(), config: Transformer.()->Unit): Transformer {
    val transformer= Transformer(transformPrioritizer)
    config(transformer)
    return transformer
}


interface Transform<IN,OUT>{

    fun isNoRepeatCall() : Boolean = true

    fun isSuppressed(obj:Any,context: TransformContext):Boolean

    fun transform(inComeObj:Any,context: TransformContext):OUT

    companion object

}

abstract class AbstractTransform<IN,OUT>: Transform<IN, OUT> {
}

class TransformContext(val paramsMap: MutableMap<String, String> = mutableMapOf()): Flag(),MutableMap<String, String> by paramsMap{}

class Transformer(transformPrioritizer: Prioritizer<Transform<Any, Any>> = DefaultPrioritizer()) {
    val transformList = transformPrioritizer.newMappingCollection()

    fun add(transform: Transform<Any, Any>){
        transformList.add(transform)
    }

    fun transform(inComeObj:Any):Any{
        return transform1(inComeObj)
    }

    private fun transform1(inComeObj:Any, lastCallIndex:Int=-1, noReportCalledIndexes:MutableSet<Int> = mutableSetOf(),context: TransformContext = TransformContext() ):Any{
        var response = inComeObj
        var callIndex = lastCallIndex

        transformList.forEachIndexedExtended{ index, _, _, transform ->
            if(callIndex != index && !noReportCalledIndexes.contains(index) && transform.isSuppressed(inComeObj,context)){
                response = transform.transform(response,context)
                callIndex = index
                if(transform.isNoRepeatCall())
                    noReportCalledIndexes.add(index)
                return@forEachIndexedExtended
            }
        }

        if(callIndex != lastCallIndex)
            return transform1(response,callIndex,noReportCalledIndexes,context)

        return response
    }

}